#ifndef DATACENTER_H
#define DATACENTER_H

#include <QWidget>
#include "QObject"
#include "../network/netclient.h"
#include "data.h"

namespace model
{

class DataCenter : public QObject
{
    Q_OBJECT

public:
    static DataCenter* getInstance();
    ~DataCenter();

private:
    DataCenter();
    static DataCenter* instance;

    // 列出 DataCenter 中要组织管理的所有的数据

    // 当前客户端登录到服务器对应的登录会话 id
    QString loginSessionId = "";

    // 当前的用户信息
    UserInfo* myself = nullptr;

    // 好友列表
    QList<UserInfo>* friendList = nullptr;

    // 会话列表
    QList<ChatSessionInfo>* chatSessionList = nullptr;
    // 记录当前选中的会话是哪个~~
    QString currentChatSessionId = "";
    // 记录每个会话中, 都有哪些成员(主要针对群聊). key 为 chatSessionId, value 为成员列表
    QHash<QString, QList<UserInfo>>* memberList = nullptr;

    // 待处理的好友申请列表
    QList<UserInfo>* applyList = nullptr;

    // 每个会话的最近消息列表, key 为 chatSessionId, value 为消息列表
    QHash<QString, QList<Message>>* recentMessages = nullptr;

    // 存储每个会话, 未读消息的个数. key 为 chatSessionId, value 为未读消息的个数.
    QHash<QString, int>* unreadMessageCount = nullptr;

    // 用户的好友搜索结果.
    QList<UserInfo>* searchUserResult = nullptr;

    // 历史消息搜索结果.
    QList<Message>* searchMessageResult = nullptr;

    // 短信验证码的验证 id
    QString currentVerifyCodeId = "1234"; //TODO

    //让DataCenter 持有 NetClient 实例
    network::NetClient netClient;


public:
    //初始化websocket
    void initWebsocketConnection();

    // 初始化数据文件
    void initDataFile();
    // 存储数据到文件中
    void saveDataFile();
    // 从数据文件中加载数据到内存
    void loadDataFile();
    //清空未读消息数目
    void clearUnread(const QString& chatSessionId);
    //增加未读消息数目
    void addUnread(const QString& chatSessionId);
    //获取未读消息数目
    int getUnreadCount(const QString& chatSessionId) const;

    // 获取当前登录会话ID
    const QString& getLoginSessionId() const
    {
        return loginSessionId;
    }

    //验证网络连通性
    void ping()
    {
        netClient.ping();
    }

    //通过网络请求获取个人信息 异步函数 http发出去就行了
    void getMyselfAsync();
    void resetMyself(const std::shared_ptr<xchat::GetUserInfoRsp>& resp);
    UserInfo* getMyself() const;

    //获取好友列表
    QList<UserInfo>* getFriendList() const;
    void getFriendListAsync();
    void resetFriendList(const std::shared_ptr<xchat::GetFriendListRsp>& resp);

    //获取会话列表
    QList<ChatSessionInfo>* getChatSessionList() const;
    void getChatSessionListAsync();
    void resetChatSessionList(const std::shared_ptr<xchat::GetChatSessionListRsp>& resp);

    //获取好友申请列表
    QList<UserInfo>* getFriendApplyList() const;
    void getFriendApplyListAsync();
    void resetFriendApplyList(const std::shared_ptr<xchat::GetPendingFriendEventListRsp>& resp);

    //获取最近消息列表
    QList<Message>* getRecentMessage(const QString& chatSessionId);
    void getRecentMessageAsync(const QString& chatSessionId, bool updateUI);
    void resetRecentMessage(const QString& chatSessionId, const std::shared_ptr<xchat::GetRecentMsgRsp>& resp);

    //根据会话ID查询会话信息
    ChatSessionInfo* findSessionById(const QString& chatSessionId);
        //设置/获取当前选中的会话ID
    void setCurrentChatSessionId(const QString& chatSessionId);
    const QString&  getCurrentChatSessionId() const;
    //根据 用户ID查询会话信息
    ChatSessionInfo* findSessionByUserId(const QString& userId);
    //置顶会话信息
    void topChatSessionInfo(const ChatSessionInfo& sessionInfo);
    //发送消息
    void sendTextMessageAsync(const QString& chatSessionId, const QString& content);
    //发送图片消息
    void sendImageMessageAsync(const QString& chatSessionId, const QByteArray& imageData);
    //发送文件消息
    void sendFileMessageAsync(const QString& chatSessionId, const QString& fileName, const QByteArray& fileData);
    //发送语音消息
    void sendSpeechMessageAsync(const QString& chatSessionId, const QByteArray& speechData);
    //语音转文字
    void speechToTextAsync(const QString &fileId, const QByteArray &speechData);
    //添加消息到DataCenter中
    void addMessage(const Message& message);
    //发起修改用户昵称请求
    void changeNicknameAsync(const QString& newNickname);
    //修改用户昵称
    void resetNickname(const QString& newNickname);
    //发起修改用户签名请求
    void changeDescriptionAsync(const QString& newDescription);
    //修改用户签名
    void resetDescription(const QString& newDescription);
    //获取验证码
    void getVerifyCodeAsync(const QString& phoneNumber);
    //发送获取当前验证码ID请求
    void resetVerifyCodeId(const QString& verifyCodeId);
    //获取当前验证码ID
    const QString& getCurrentVerifyCodeId() const;
    //发送尝试修改手机号请求
    void changePhoneNumberAsync(const QString& newPhoneNumber, const QString& verifyCodeId, const QString& userInputCode);
    //修改手机号
    void resetPhoneNumber(const QString& newPhoneNumber);
    //修改头像
    void changeAvatarAsync(const QByteArray& newAvatarData);
    //重置头像
    void resetAvatar(const QByteArray& newAvatarData);
    //查看是否是好友
    UserInfo* findFriendById(const QString& userId);
    //删除好友
    void deleteFriendAsync(const QString& userId);
    //删除好友处理
    void removeFriend(const QString& userId);
    //添加好友申请
    void addFriendApplyAsync(const QString& userId);
    //同意好友申请
    void acceptFriendApplyAsync(const QString& userId);
    //移除好友申请
    UserInfo removeFriendApply(const QString& userId);
    //拒绝好友申请
    void rejectFriendApplyAsync(const QString& userId);
    //创建群聊
    void createGroupChatSessionAsync(const QList<QString>& memberUserIds);
    //获取群聊会话成员列表
    void getMemberList(const QString& chatSessionId);
    //获取指定会话的成员列表
    void resetChatSessionMemberList(const QString& chatSessionId, const QList<xchat::UserInfo>& memberInfos);
    //获取指定会话的成员列表指针
    QList<UserInfo>* getChatSessionMemberList(const QString& chatSessionId);
    //搜索用户
    void searchUserAsync(const QString& keyword);
    // 保存用户搜索结果
    void resetSearchUserList(const QList<xchat::UserInfo>& searchInfos);
    // 获取用户搜索结果
    QList<UserInfo>* getSearchUserResult();
    // 搜索历史消息
    void searchHistoryMessageAsync(const QString& keyword);
    // 保存历史消息搜索结果
    void resetSearchMessageList(const QList<xchat::MessageInfo>& messageInfos);
    // 获取历史消息搜索结果
    QList<Message>* getSearchMessageResult();
    // 按时间搜索历史消息
    void searchHistoryMessageByTimeAsync(const QDateTime& begTime, const QDateTime& endTime);
    // 用户登录请求
    void userLoginAsync(const QString& userName, const QString& password);
    // 设置登录会话Id
    void resetLoginSessionId(const QString& sessionId);
    // 用户注册
    void userRegisterAsync(const QString& userName, const QString& password);
    // 用户手机号登录
    void phoneLoginAsync(const QString& phoneNumber, const QString& verifyCode);
    // 用户手机号注册
    void phoneRegisterAsync(const QString& phoneNumber, const QString& verifyCode);
    // 获取单个文件
    void getSingleFileAsync(const QString& fileId);


signals:
    //自定义信号
    void getMyselfDone();
    void getFriendListDone();
    void getChatSessionListDone();
    void getFriendApplyListDone();
    void getRecentMessageDone(const QString& chatSessionId);
    void sendMessageDone(Message_Type messageType, const QByteArray& content, const QString& extraInfo);
    void updateLastMessage(const QString& chatSessionId);
    void getRecentMessageNoUIDone(const QString& chatSessionId);
    void receiveMessageDone(const Message& lastMessage);
    void changeNicknameDone();
    void changeDescriptionDone();
    void getVerifyCodeDone();
    void changePhoneNumberDone();
    void changeAvatarDone();
    void deleteFriendDone();
    void clearCurrentChatSession();
    void addFriendApplyDone();
    void receiveFriendApplyDone();
    void acceptFriendApplyDone();
    void receiveFriendProcessDone(const QString& nickName, bool isAccepted);
    void rejectFriendApplyDone();
    void createGroupChatSessionDone();
    void receiveCreateGroupChatSessionDone(const QString& newChatSessionName);
    void getMemberListDone(const QString &chatSessionId);
    void searchUserDone();
    void searchHistoryMessageDone();
    void userLoginDone(bool success, const QString& reason);
    void userRegisterDone(bool success, const QString& reason);
    void phoneLoginDone(bool success, const QString& reason);
    void phoneRegisterDone(bool success, const QString& reason);
    void getSingleFileDone(const QString& fileId, const QByteArray& fileData);
    void speechToTextDone(const QString& fileId, const QString& fileData);
};

}   //end namespace model
#endif // DATACENTER_H













